package ldh.common.testui.component;

import com.google.gson.reflect.TypeToken;
import com.jfoenix.controls.*;
import com.jfoenix.validation.RequiredFieldValidator;
import com.jfoenix.validation.base.ValidatorBase;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import ldh.common.json.ChangeField;
import ldh.common.json.ExclusionField;
import ldh.common.json.JsonViewFactory;
import ldh.common.testui.cell.ObjectTableCellFactory;
import ldh.common.testui.constant.ParamType;
import ldh.common.testui.dao.TestHttpParamDao;
import ldh.common.testui.model.TestCookie;
import ldh.common.testui.model.TestHttp;
import ldh.common.testui.model.TestHttpParam;
import ldh.common.testui.util.DialogUtil;
import ldh.common.testui.util.JFoenixUtil;
import ldh.common.testui.util.ThreadUtilFactory;
import ldh.common.testui.util.UiUtil;
import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by ldh123 on 2017/6/21.
 */
public class HttpCookieControl extends StackPane {

    @FXML private TableView<TestCookie> tableView;
    @FXML private TableColumn<TestHttpParam, Boolean> checkBoxTableColumn;

    private TestHttp testHttp;
    private TestHttpParam testHttpParam = null;
    private ObservableList<TestCookie> tableValues = FXCollections.observableArrayList();
    private TestCookie editCookie = null;

    @FXML private JFXTextField nameTextField;
    @FXML private JFXTextField valueTextField;
    @FXML private JFXTextField domainTextField;
    @FXML private JFXTextField pathTextField;
    @FXML private JFXDatePicker datePicker;
    @FXML private JFXTimePicker timePicker;
    @FXML private CheckBox secureCheckBox;

    @FXML private Pane tablePane;
    @FXML private GridPane editPane;

    private List<ValidatorBase> formValidatorBases = new ArrayList();

    public HttpCookieControl() throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/control/fxml/HttpCookie.fxml"));
        loader.setRoot(this);
        loader.setController(this);
        loader.load();

        tableView.setItems(tableValues);
    }

    @FXML
    public void initialize() {
        this.getChildren().remove(editPane);

//        validationSupport.registerValidator(nameTextField, Validator.createEmptyValidator("Name不能为空"));
//        validationSupport.registerValidator(valueTextField, Validator.createEmptyValidator("Value不能为空"));
//        validationSupport.registerValidator(domainTextField, Validator.createEmptyValidator("Domain不能为空"));
//        validationSupport.registerValidator(pathTextField, Validator.createEmptyValidator("Path不能为空"));
        tableView.setEditable(true);
        checkBoxTableColumn.setCellFactory(CheckBoxTableCell.forTableColumn(checkBoxTableColumn));
        checkBoxTableColumn.setStyle("-fx-alignment:center");

        RequiredFieldValidator nameValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), nameTextField);
        RequiredFieldValidator valueValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), valueTextField);
        RequiredFieldValidator domainValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), domainTextField);
        RequiredFieldValidator pathValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), pathTextField);
        RequiredFieldValidator dateValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), datePicker);
        RequiredFieldValidator timeValidator = JFoenixUtil.createValidatorBase(new RequiredFieldValidator(), timePicker);

        formValidatorBases.addAll(Arrays.asList(nameValidator, valueValidator, domainValidator, pathValidator, dateValidator, timeValidator));

        timePicker.set24HourView(true);

        tableValues.addListener((ListChangeListener) c->{
            while(c.next()) {
                if (c.wasAdded()) {
                    List<TestCookie> testCookies = c.getAddedSubList();
                    testCookies.forEach(testCookie -> {
                        testCookie.enableProperty().addListener((b, o, n)->{
                            testCookie.setSelect(n);
                            updateTestHttpParam();
                        });
                    });
                }
            }

        });
    }


    public void initData(TestHttpParam testHttpParam) {
        this.testHttpParam = testHttpParam;
        String context = testHttpParam.getContent();
        List<TestCookie> testCookieList = JsonViewFactory.create().setExclusionStrategy(new ExclusionField("enable")).fromJson(context, new TypeToken<List<TestCookie>>(){}.getType());
        testCookieList.forEach(testCookie -> testCookie.setNew(true));
        tableValues.addAll(testCookieList);
    }

    public void setTestHttp(TestHttp testHttp) {
        this.testHttp = testHttp;
    }

    @FXML public void add() {
        if (testHttp == null) {
            DialogUtil.alert("请输入http地址", Alert.AlertType.ERROR);
            return;
        }
        editCookie = null;

        nameTextField.setText("");
        valueTextField.setText("");
        domainTextField.setText("");
        pathTextField.setText("");
        datePicker.setValue(null);
        timePicker.setValue(null);
        secureCheckBox.setSelected(false);

        JFXDialog editDialog = DialogUtil.createDialog(editPane, "添加cookie", (jfxDialog, jfxDialogLayout) -> {
            JFXButton saveButton = new JFXButton("Add");
            saveButton.getStyleClass().add("dialog-accept");
            saveButton.setOnAction(e->saveTestCookieAtn(jfxDialog));
            return Arrays.asList(saveButton);
        });
        editDialog.show();
    }

    @FXML public void edit() {
        if (testHttp == null) {
            DialogUtil.alert("请输入http地址", Alert.AlertType.ERROR);
            return;
        }
        TestCookie testCookie = tableView.getSelectionModel().getSelectedItem();
        if (testCookie == null) {
            DialogUtil.alert("请选择一行需要修改的数据", Alert.AlertType.ERROR);
            return;
        }
        editCookie = testCookie;

        nameTextField.setText(editCookie.getName());
        valueTextField.setText(editCookie.getValue());
        domainTextField.setText(editCookie.getDomain());
        pathTextField.setText(editCookie.getPath());
        LocalDateTime localDateTime = LocalDateTime.parse(editCookie.getExpires(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        datePicker.setValue(localDateTime.toLocalDate());
        timePicker.setValue(localDateTime.toLocalTime());
        secureCheckBox.setSelected(editCookie.isSecure());

        JFXDialog editDialog = DialogUtil.createDialog(editPane, "修改cookie", (jfxDialog, jfxDialogLayout) -> {
            JFXButton saveButton = new JFXButton("Save");
            saveButton.getStyleClass().add("dialog-accept");
            saveButton.setOnAction(e->saveTestCookieAtn(jfxDialog));
            return Arrays.asList(saveButton);
        });
        editDialog.show();
    }

    @FXML public void remove() {
        TestCookie testCookie = tableView.getSelectionModel().getSelectedItem();
        if (testCookie != null) {
            tableValues.remove(testCookie);

            try {
                updateTestHttpParam();
            } catch (Exception e) {
                tableValues.add(testCookie);
                DialogUtil.alert("保存失败", Alert.AlertType.ERROR);
            }
        } else {
            DialogUtil.alert("请选择一行需要删除的数据", Alert.AlertType.ERROR);
        }
    }

    private void saveTestCookieAtn(JFXDialog editDialog) {
        formValidatorBases.forEach(validatorBase -> {
            validatorBase.validate();
        });
        long errorTotal = formValidatorBases.stream().filter(validatorBase -> validatorBase.getHasErrors()).count();
        if (errorTotal > 0) {
            DialogUtil.alert("请按要求填写", Alert.AlertType.WARNING);
            return;
        }
        TestCookie testCookie = buildTestCookie();
        if (editCookie == null) {
            int id = 1;
            if (tableValues.size() >= 1) {
                id = tableValues.get(tableValues.size()-1).getId();
            }
            testCookie.setId(id + 1);
            tableValues.add(testCookie);
        } else {
            List<TestCookie> testCookies = tableValues.stream().filter(testCookie1 -> !testCookie1.getId().equals(testCookie.getId())).collect(Collectors.toList());
            testCookies.add(testCookie);
            testCookies = testCookies.stream().sorted(Comparator.comparing(t->t.getId())).collect(Collectors.toList());
            tableValues.clear();
            tableValues.setAll(testCookies);
        }

        updateTestHttpParam();

        editDialog.close();
    }

    @FXML public void closeEditPaneAtn() {
        UiUtil.transitionPane(editPane, tablePane, (Void)->{});
    }

    private void updateTestHttpParam() {
        ThreadUtilFactory.getInstance().submit(()->{
            try {
                List<TestCookie> testCookies = tableView.getItems();
                List<TestCookie> updateTestCookies = testCookies.stream().collect(Collectors.toList());
                String json = JsonViewFactory.create()
                        .setExclusionStrategy(new ExclusionField("enable"))
                        .toJson(updateTestCookies);
                if (testHttpParam == null) {
                    testHttpParam = new TestHttpParam();
                }
                testHttpParam.setContent(json);
                testHttpParam.setParamType(ParamType.Cookie);
                testHttpParam.setTestHttpId(testHttp.getId());
                TestHttpParamDao.save(testHttpParam);
            } catch (Exception e) {
                e.printStackTrace();
                Platform.runLater(()->DialogUtil.alert("保存失败", Alert.AlertType.ERROR));
            }
            return null;
        }, null);

    }

    private void refresh() {
        tableView.setItems(tableValues);
        System.out.println("size: " + tableValues.size());
        tableView.refresh();
    }

    private TestCookie buildTestCookie() {
        String name = nameTextField.getText();
        String value = valueTextField.getText();
        String domain = domainTextField.getText();
        String path = pathTextField.getText();
        LocalDate localDate = datePicker.getValue();
        LocalTime localTime = timePicker.getValue();
        String expires = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        boolean secure = secureCheckBox.isSelected();
        TestCookie newTestCookie = new TestCookie(name, value, domain, path, expires, secure);
        if (editCookie != null) {
            newTestCookie.setId(editCookie.getId());
        }
        return newTestCookie;
    }
}
